#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "aimage.h"
#include "aimage_ppm.h"

void AIMAGE_PPM_UTILS::load( AIMAGE &dst, const char *filename )
{
	FILE *f;
	char buffer[ 256 ];
	int width, height;

	if ( strcmp( filename, "stdin" ) == 0)
	{
		f = stdin;
	}
	else
	{
		f = fopen( filename, "rb");
	}
	if ( f == NULL )
	{
		fprintf(stderr,"Unable to open \"%s\"", filename );
		assert( 0 );
	}
	
	fgets( buffer, 256, f );
	assert( strcmp( buffer, "P6\n") == 0 );
	
	fgets( buffer, 256, f );
	sscanf(buffer, "%d %d", &width, &height );
	dst.alloc_image( width, height );

	AIMAGE::iterator begin;
	AIMAGE::iterator end;
	AIMAGE::iterator itr;
	begin = dst.begin();
	end = dst.end();

	fgets( buffer, 256, f );
	if ( strcmp( buffer, "255\n") == 0 )
	{
		unsigned char *big_buffer;
		unsigned char *sptr;
		big_buffer = new unsigned char[ width * height * 3 ];

		fread( big_buffer, width * height * 3, 1, f );
		sptr = big_buffer;

		for ( itr = begin; itr != end; ++itr )
		{
			APIXEL *cur = &(*itr);
			cur->r = ((int) sptr[0]) * FULL_INT / 255;
			cur->g = ((int) sptr[1]) * FULL_INT / 255;
			cur->b = ((int) sptr[2]) * FULL_INT / 255;
			sptr+=3;
		}
		delete[] big_buffer;
	}
	else if ( strcmp( buffer, "65535\n") == 0 )
	{
		unsigned char *big_buffer;
		big_buffer = new unsigned char[ width * height * 3 * 2 ];
		unsigned char *sptr;

		assert( FULL_INT == 65535 );

		fread( big_buffer, width * height * 3 * 2, 1, f );
		sptr = big_buffer;

		for ( itr = begin; itr != end; ++itr )
		{
			APIXEL *cur = &(*itr);
			int low,hi;
			hi=sptr[0] ; low=sptr[1];
			sptr+=2;
			cur->r = low | ( hi << 8 );
			hi=sptr[0] ; low=sptr[1];
			sptr+=2;
			cur->g = low | ( hi << 8 );
			hi=sptr[0] ; low=sptr[1];
			sptr+=2;
			cur->b = low | ( hi << 8 );
		}
		delete[] big_buffer;
	}

	if ( f != stdin )
	{
		fclose( f );
	}
}

void AIMAGE_PPM_UTILS::save( const AIMAGE &src, const char *filename, bool bit16 )
{
	FILE *f;
	int width, height;

	src.get_dim( width, height );

	if ( strcmp( filename, "stdout" ) == 0)
	{
		f = stdout;
	}
	else
	{
		f = fopen( filename, "wb");
	}
	if ( f == NULL )
	{
		fprintf(stderr,"Unable to open %s", filename );
	}
	
	fprintf(f, "P6\n");
	fprintf(f, "%d %d\n", width, height );
	if ( bit16 )
	{
		fprintf(f, "65535\n");
	}
	else
	{
		fprintf(f, "255\n");
	}

	AIMAGE::const_iterator begin;
	AIMAGE::const_iterator end;
	AIMAGE::const_iterator itr;

	begin = src.const_begin();
	end = src.const_end();

	assert( FULL_INT == 65535 );

	if ( bit16 )
	{
		unsigned char *big_buffer;
		unsigned char *sptr;
		big_buffer = new unsigned char[ width * height * 3 * 2 ];
		sptr=big_buffer;
		
		for ( itr = begin; itr != end; ++itr )
		{
			const APIXEL *cur = &(*itr);
			int low, hi;
			low = cur->r & 0xff; hi = cur->r >> 8;
			*sptr++=hi; *sptr++=low;
			low = cur->g & 0xff; hi = cur->g >> 8;
			*sptr++=hi; *sptr++=low;
			low = cur->b & 0xff; hi = cur->b >> 8;
			*sptr++=hi; *sptr++=low;
		}
		fwrite( big_buffer, width*height*3*2, 1, f );
		delete[] big_buffer;
	}
	else
	{
		for ( itr = begin; itr != end; ++itr )
		{
			const APIXEL *cur = &(*itr);
			fputc( cur->r / 256, f );
			fputc( cur->g / 256, f );
			fputc( cur->b / 256, f );
		}
	}
	fclose( f );
}


